﻿using System;
using System.Diagnostics.Contracts;
using Elderos.Utils.Logging;

namespace Elderos.Geometry
{
	public struct Point
	{
		public readonly double[] Coordinates;

		public Point(params double[] coordinates)
		{
			Logger.Assert(() => coordinates.Length > 0,
						  "Can't create point in a zero dimensions space.",
						  typeof(ArgumentException));
			Coordinates = coordinates;
		}

		public int Dimensions
		{
			get { return Coordinates.Length; }
		}

		public override string ToString()
		{
			return "[" + string.Join(", ", Coordinates) + "]";
		}


		/// <summary>
		/// Calculates Minkovsky distance between two points in a multidimensional space.
		/// Both point must have equal dimensions count.
		/// </summary>
		/// <param name="p1">First point</param>
		/// <param name="p2">Second point</param>
		/// <param name="dimensions">Optional parameter - count of dimensions accounted.
		/// Value "1" means Cityblock distance, "2" - Euclidian distance.
		/// Can't be more than dimensions count of points. The less is the difference
		/// between this parameter and point dimesions count, the smaller is the distortion.
		/// If there is too many dimensions, the precision can be lost (it's depending on double limits).</param>
		/// <returns></returns>
		public static double GetMinkovskyDistance(Point p1, Point p2, int dimensions = 0)
		{
			double result = 0;
            if (dimensions == 0)
                dimensions = Math.Min(p1.Dimensions, p2.Dimensions);

			for (int i = 0; i < dimensions; i++)
				result += Math.Pow(Math.Abs(p1.Coordinates[i] - p2.Coordinates[i]), dimensions);

			return Math.Pow(result, 1.0/dimensions);
		}
	}
}